package com.kongzue.baseokhttp.util;

import com.kongzue.baseokhttp.listener.*;
import okhttp3.Cookie;
import okhttp3.HttpUrl;

import java.net.Proxy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * Author: @Kongzue
 * Github: https://github.com/kongzue/
 * Homepage: http://kongzue.com/
 * Mail: myzcxhh@live.cn
 * CreateTime: 2018/12/5 17:48
 */
public class BaseOkHttpConfig {

    private volatile static BaseOkHttpConfig instance;

    /**
     * 是否开启调试模式
     */
    private boolean debugMode = false;

    /**
     * 超时时长（单位：秒）
     */
    private int timeOutDuration = 10;

    /**
     * 默认服务器地址
     */
    private String serviceUrl = "";

    /**
     * Https请求需要传入Assets目录下的证书文件名称
     */
    private String SSLInAssetsFileName;

    /**
     * Https请求是否需要Hostname验证，请保证serviceUrl中即Hostname地址
     */
    private boolean httpsVerifyServiceUrl = false;

    /**
     * 全局拦截器
     */
    private BaseResponseInterceptListener responseInterceptListener;

    /**
     * 全局参数拦截器
     */
    private ParameterInterceptListener parameterInterceptListener;

    /**
     * 全局Header拦截器
     */
    private HeaderInterceptListener headerInterceptListener;

    /**
     * 全局请求头
     */
    private Parameter overallHeader;

    /**
     * 全局参数
     */
    private Parameter overallParameter;

    /**
     * WebSocket自动重连步长（单位：秒）
     */
    private int websocketReconnectInterval = 10;

    /**
     * WebSocket最大重连间隔（单位：秒）
     */
    private int websocketReconnectTime = 120;

    /**
     * 自动缓存 Cookies
     */
    private boolean autoSaveCookies;

    /**
     * 容灾地址
     */
    private String[] reserveServiceUrls;

    /**
     * 是否开启详细日志信息（下载、线程提升信息）
     */
    private boolean detailsLogs = false;

    /**
     * 全局代理设置
     */
    private Proxy proxy;

    /**
     * 禁止重复请求
     */
    private boolean disallowSameRequest;

    /**
     * 缓存请求
     */
    private boolean requestCache = true;

    /**
     * 全局自定义 OkHttpClient
     */
    private GlobalCustomOkHttpClient globalCustomOkHttpClient;

    /**
     * 全局自定义 OkHttpClientBuilder
     */
    private GlobalCustomOkHttpClientBuilder globalCustomOkHttpClientBuilder;

    /**
     * getSSLInAssetsFileName
     *
     * @return String
     */
    public String getSSLInAssetsFileName() {
        return SSLInAssetsFileName;
    }

    /**
     * setSSLInAssetsFileName
     *
     * @param SSLInAssetsFileName SSLInAssetsFileName
     */
    public void setSSLInAssetsFileName(String SSLInAssetsFileName) {
        this.SSLInAssetsFileName = SSLInAssetsFileName;
    }

    /**
     * getParameterInterceptListener
     *
     * @return ParameterInterceptListener
     */
    public ParameterInterceptListener getParameterInterceptListener() {
        return parameterInterceptListener;
    }

    /**
     * setParameterInterceptListener
     *
     * @param parameterInterceptListener parameterInterceptListener
     */
    public void setParameterInterceptListener(ParameterInterceptListener parameterInterceptListener) {
        this.parameterInterceptListener = parameterInterceptListener;
    }

    /**
     * getHeaderInterceptListener
     *
     * @return HeaderInterceptListener
     */
    public HeaderInterceptListener getHeaderInterceptListener() {
        return headerInterceptListener;
    }

    /**
     * setHeaderInterceptListener
     *
     * @param headerInterceptListener headerInterceptListener
     */
    public void setHeaderInterceptListener(HeaderInterceptListener headerInterceptListener) {
        this.headerInterceptListener = headerInterceptListener;
    }

    /**
     * getOverallHeader
     *
     * @return Parameter
     */
    public Parameter getOverallHeader() {
        return overallHeader;
    }

    /**
     * setOverallHeader
     *
     * @param overallHeader overallHeader
     */
    public void setOverallHeader(Parameter overallHeader) {
        this.overallHeader = overallHeader;
    }

    /**
     * getOverallParameter
     *
     * @return Parameter
     */
    public Parameter getOverallParameter() {
        return overallParameter;
    }

    /**
     * setOverallParameter
     *
     * @param overallParameter overallParameter
     */
    public void setOverallParameter(Parameter overallParameter) {
        this.overallParameter = overallParameter;
    }

    /**
     * boolean
     *
     * @return isAutoSaveCookies
     */
    public boolean isAutoSaveCookies() {
        return autoSaveCookies;
    }

    /**
     * setAutoSaveCookies
     *
     * @param autoSaveCookies autoSaveCookies
     */
    public void setAutoSaveCookies(boolean autoSaveCookies) {
        this.autoSaveCookies = autoSaveCookies;
    }

    /**
     * getProxy
     *
     * @return Proxy
     */
    public Proxy getProxy() {
        return proxy;
    }

    /**
     * setProxy
     *
     * @param proxy proxy
     */
    public void setProxy(Proxy proxy) {
        this.proxy = proxy;
    }

    /**
     * isDisallowSameRequest
     *
     * @return boolean
     */
    public boolean isDisallowSameRequest() {
        return disallowSameRequest;
    }

    /**
     * setDisallowSameRequest
     *
     * @param disallowSameRequest disallowSameRequest
     */
    public void setDisallowSameRequest(boolean disallowSameRequest) {
        this.disallowSameRequest = disallowSameRequest;
    }

    /**
     * getGlobalCustomOkHttpClient
     *
     * @return GlobalCustomOkHttpClient
     */
    public GlobalCustomOkHttpClient getGlobalCustomOkHttpClient() {
        return globalCustomOkHttpClient;
    }

    /**
     * setGlobalCustomOkHttpClient
     *
     * @param globalCustomOkHttpClient globalCustomOkHttpClient
     */
    public void setGlobalCustomOkHttpClient(GlobalCustomOkHttpClient globalCustomOkHttpClient) {
        this.globalCustomOkHttpClient = globalCustomOkHttpClient;
    }

    /**
     * getGlobalCustomOkHttpClientBuilder
     *
     * @return GlobalCustomOkHttpClientBuilder
     */
    public GlobalCustomOkHttpClientBuilder getGlobalCustomOkHttpClientBuilder() {
        return globalCustomOkHttpClientBuilder;
    }

    /**
     * setGlobalCustomOkHttpClientBuilder
     *
     * @param globalCustomOkHttpClientBuilder globalCustomOkHttpClientBuilder
     */
    public void setGlobalCustomOkHttpClientBuilder(GlobalCustomOkHttpClientBuilder globalCustomOkHttpClientBuilder) {
        this.globalCustomOkHttpClientBuilder = globalCustomOkHttpClientBuilder;
    }

    /**
     * cleanSameRequestList
     */
    public static void cleanSameRequestList() {
        requestInfoList = new ArrayList<>();
    }

    private static List<RequestInfo> requestInfoList;

    /**
     * getInstance
     *
     * @return BaseOkHttpConfig
     */
    public static BaseOkHttpConfig getInstance() {
        if (instance == null) {
            synchronized (BaseOkHttp.class) {
                if (instance == null) {
                    instance = new BaseOkHttpConfig();
                }
            }
        }
        return instance;
    }

    /**
     * getWebsocketReconnectInterval
     *
     * @return int
     */
    public int getWebsocketReconnectInterval() {
        return websocketReconnectInterval;
    }

    /**
     * setWebsocketReconnectInterval
     *
     * @param websocketReconnectInterval websocketReconnectInterval
     */
    public void setWebsocketReconnectInterval(int websocketReconnectInterval) {
        this.websocketReconnectInterval = websocketReconnectInterval;
    }

    /**
     * getResponseInterceptListener
     *
     * @return BaseResponseInterceptListener
     */
    public BaseResponseInterceptListener getResponseInterceptListener() {
        return responseInterceptListener;
    }

    /**
     * setResponseInterceptListener
     *
     * @param responseInterceptListener responseInterceptListener
     */
    public void setResponseInterceptListener(BaseResponseInterceptListener responseInterceptListener) {
        this.responseInterceptListener = responseInterceptListener;
    }

    /**
     * isHttpsVerifyServiceUrl
     *
     * @return boolean
     */
    public boolean isHttpsVerifyServiceUrl() {
        return httpsVerifyServiceUrl;
    }

    /**
     * setHttpsVerifyServiceUrl
     *
     * @param httpsVerifyServiceUrl httpsVerifyServiceUrl
     */
    public void setHttpsVerifyServiceUrl(boolean httpsVerifyServiceUrl) {
        this.httpsVerifyServiceUrl = httpsVerifyServiceUrl;
    }

    /**
     * getReserveServiceUrls
     *
     * @return
     */
    public String[] getReserveServiceUrls() {
        return reserveServiceUrls == null ? null : reserveServiceUrls.clone();
    }

    /**
     * setReserveServiceUrls
     *
     * @param reserveServiceUrls reserveServiceUrls
     */
    public void setReserveServiceUrls(String[] reserveServiceUrls) {
        if (reserveServiceUrls != null) {
            this.reserveServiceUrls = reserveServiceUrls.clone();
        } else {
            this.reserveServiceUrls = null;
        }
    }

    /**
     * getServiceUrl
     *
     * @return String
     */
    public String getServiceUrl() {
        return serviceUrl;
    }

    /**
     * setServiceUrl serviceUrl
     *
     * @param serviceUrl serviceUrl
     */
    public void setServiceUrl(String serviceUrl) {
        this.serviceUrl = serviceUrl;
    }

    /**
     * isRequestCache
     *
     * @return boolean
     */
    public boolean isRequestCache() {
        return requestCache;
    }

    /**
     * setRequestCache
     *
     * @param requestCache requestCache
     */
    public void setRequestCache(boolean requestCache) {
        this.requestCache = requestCache;
    }

    /**
     * getTimeOutDuration
     *
     * @return int
     */
    public int getTimeOutDuration() {
        return timeOutDuration;
    }

    /**
     * setTimeOutDuration
     *
     * @param timeOutDuration timeOutDuration
     */
    public void setTimeOutDuration(int timeOutDuration) {
        this.timeOutDuration = timeOutDuration;
    }

    /**
     * getWebsocketReconnectTime
     *
     * @return int
     */
    public int getWebsocketReconnectTime() {
        return websocketReconnectTime;
    }

    /**
     * setWebsocketReconnectTime
     *
     * @param websocketReconnectTime websocketReconnectTime
     */
    public void setWebsocketReconnectTime(int websocketReconnectTime) {
        this.websocketReconnectTime = websocketReconnectTime;
    }

    /**
     * isDetailsLogs
     *
     * @return boolean
     */
    public boolean isDetailsLogs() {
        return detailsLogs;
    }

    /**
     * setDetailsLogs
     *
     * @param detailsLogs detailsLogs
     */
    public void setDetailsLogs(boolean detailsLogs) {
        this.detailsLogs = detailsLogs;
    }

    public boolean isDebugMode() {
        return debugMode;
    }

    public void setDebugMode(boolean debugMode) {
        this.debugMode = debugMode;
    }

    /**
     * addRequestInfo
     *
     * @param requestInfo requestInfo
     */
    protected void addRequestInfo(RequestInfo requestInfo) {
        synchronized (BaseOkHttp.class) {
            if (requestInfoList == null) {
                requestInfoList = new ArrayList<>();
            }
            if (debugMode) {
                LockLog.logI(">>>", "addRequestInfo: " + requestInfo);
            }
            requestInfoList.add(requestInfo);
        }
    }

    /**
     * deleteRequestInfo
     *
     * @param requestInfo requestInfo
     */
    protected void deleteRequestInfo(RequestInfo requestInfo) {
        synchronized (BaseOkHttp.class) {
            if (requestInfoList == null || requestInfoList.isEmpty() || requestInfo == null) {
                return;
            }
            requestInfoList.remove(requestInfo);
        }
    }

    /**
     * equalsRequestInfo
     *
     * @param requestInfo requestInfo
     * @return boolean
     */
    protected boolean equalsRequestInfo(RequestInfo requestInfo) {
        synchronized (BaseOkHttp.class) {
            if (requestInfoList == null || requestInfoList.isEmpty()) {
                if (debugMode) {
                    LockLog.logI(">>>", "requestInfoList: null");
                }
                return false;
            }
            for (RequestInfo requestInfo1 : requestInfoList) {
                if (debugMode) {
                    LockLog.logI(">>>", "equalsRequestInfo: " + requestInfo1);
                }
                if (requestInfo1.equals(requestInfo)) {
                    if (debugMode) {
                        LockLog.logI(">>>", "发生重复请求");
                    }
                    return true;
                }
            }
            return false;
        }
    }
}
